package com.xinz.srmi.impl.serialization;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import com.xinz.srmi.Log;


public class BeanInputStream extends DataInputStream {
	StreamContext context;
	/**
	 * 缓存区的对象
	 */
	ArrayList<Object> buffList = new ArrayList<Object>();

	public BeanInputStream(InputStream in,StreamContext context) {
		super(in);
		this.context = context;
	}
	public BeanInputStream(InputStream in) {
		this(in, new StreamContext());
	}

	/**
	 * 读取一个对象
	 * @return
	 * @throws Exception
	 */
	public Object readObject() throws Exception {
		Accessor accessor = new ObjectAccessor();
		try {
			readAccssor(accessor);
			return accessor.get();
		} catch (Exception e) {
			throw e;
		} finally {
			clearBuff();
		}
	}

	private void clearBuff() {
		buffList.clear();
	}
	/**
	 * 读取一个序列化实现对象
	 * @return
	 * @throws IOException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	private Serialer readSerialer() throws IOException, IllegalAccessException,
			ClassNotFoundException {
		int id = readShort();
		Serialer serialer;
		if (id < 0) {
			Class<?> clazz = readClass();
			int fieldSize = readShort();
			String[] fields = new String[fieldSize];
			for (int i = 0; i < fields.length; i++) {
				fields[i] = readUTF();
			}
			serialer = new ObjectSerialer(clazz,fields);
			
			context.addSerialer(serialer);
		} else {
			serialer = context.getDynamic(id);
		}
		return serialer;
	}
	
	Class<?> readClass() throws IOException, ClassNotFoundException {
		int index = readShort();
		Class<?> result;
		if(index<0){
			result = Class.forName(readUTF());
			context.addClass(result);
		}else{
			result = context.getClass(index);
		}
		return result;
	}

	void addBuff(Object obj) {
		buffList.add(obj);
	}
/**
 * 读取一个对象或者字段，并根据读取类型填充到Accessor里
 * @param accessor
 * @throws Exception
 */
	public void readAccssor(Accessor accessor) throws Exception {
		int flag = read();
		Serialer serialer;
		int index;
			switch (flag) {
			case StreamContext.HEAD_EMPTY:
				break;
			case StreamContext.HEAD_NULL:
				accessor.set(null);
				break;
			case StreamContext.HEAD_BASE:
				index = readShort();
				serialer = context.getBase(index);
				serialer.read(accessor, this);
				break;
			case StreamContext.HEAD_REF:
				index = readShort();
				accessor.set(buffList.get(index));
				break;
			case StreamContext.HEAD_NEW:
				accessor.set(null);
				while (true) {
					serialer = readSerialer();
					try{
						serialer.read(accessor, this);
						Class superClazz = serialer.getType().getSuperclass();
						if (superClazz == null || superClazz == Object.class||superClazz==Exception.class) {
							break;
						}
					}catch (Exception e) {
						Log.info("读取对象 失败 type:"+serialer.getType());
						e.printStackTrace();
					}
				}
				
				break;
			}
		
		
	}
}
